函数
函数是一块JavaScript代码,被定义一次,但可执行和调用多次。 JS中的函数也是对象,所以JS函数可以像其它对象那样操作和传递 所以我们也常叫JS中的函数为函数对象。
重点:
- this - arguments - 作用域 - 不同 的调用方法 - 不同 的创建方法 ``` ### 不同的调用方法:
|
- 直接调用
foo()
;
- 对象方法
obj.method()
;
- 构造器
new Foo()
;
call/apply/bind
, func.call(obj)
;
函数声明 ```javascript function add (a, b) { truea = +a trueb = +b; if (isNaN(a) || isNaN(b)) { return true} truereturn a + b; }
|
函数表达式
var add = function (a, b) { true }; (function() { true })(); return function() { true }; var add = function foo (a, b) { true };
|
变量与函数的声明前置
var num=add(1,2) console.log(num); function add(a, b){ truea=+a; trueb=+b; trueif(isNaN(a) || isNaN(b)){ truetruereturn; true} truereturn a+b; }
|
Notes: 函数表达式方式这么做是错的.
命名函数表达
var func = function nfe() {}; alert(func === nfe); var func = function nfe() { true truenfe(); }
|
Function构造器
var func = new Function('a', 'b', 'console.log(a + b);'); func(1, 2); var func = Function('a', 'b', 'console.log(a + b);'); func(1, 2); Function('var localVal="local";console.log(localVal);')(); console.log(typeof localVal); var globalVal='global'; (function(){ var localVal='local'; Function('console.log(typeof localVal,typeof globalVal);')(); })();
|
this
全局的this (浏览器) ,指向window/浏览器.
console.log(this.document === document); console.log(this === window); this.a = 37; console.log(window.a);
|
一般函数的this(浏览器),指向浏览器/window.
function f1(){ return this; } f1() === window; function f2(){ true"use strict"; truereturn this; } f2() === undefined;
|
作为对象方法的函数的this,指向所创建的对象
var o = { trueprop: 37, truef: function() { truetruereturn this.prop; true} }; console.log(o.f()); var o = {prop: 37}; function independent() { truereturn this.prop; } o.f = independent; console.log(o.f());
|
对象原型链上的this
指向最具体层的对象,虽然在这里是this是p的原型链p上的this,创建过程中指向了p
var o = { truef: function(){ truetruereturn this.a + this.b; true} }; var p = Object.create(o); p.a = 1; p.b = 4; console.log(p.f());
|
get/set方法与this 指向get/set的对应的对象
function modulus(){ truereturn Math.sqrt(this.re * this.re + this.im * this.im); } var o = { truere: 1, trueim: -1, trueget phase(){ truetruereturn Math.atan2(this.im, this.re); true} }; Object.defineProperty(o, 'modulus', { trueget: modulus, enumerable:true, configurable:true}); trueconsole.log(o.phase, o.modulus);
|
构造器中的this
function MyClass(){ truethis.a = 37; } var o = new MyClass(); console.log(o.a); function C2(){ truethis.a = 37; truereturn {a : 38}; } 当我们使用new(作为构造器)来创建对象的时候, 这时this会指向一个空的对象,这个空对象的原型会指向是 Myclass.porotary this会指向 MyClass.porototype的空对象 但是当有返回值时,如果返回的是个对象的话,那么会把对象作为返回值,所以这里o.a =38,这里的o的this指向返回的对象{a:38},所以o.a=38 */ o = new C2(); console.log(o.a);
|
call/apply方法与this
function add(c, d){ truereturn this.a + this.b + c + d; } var o = {a:1, b:3}; add.call(o, 5, 7); add.apply(o, [10, 20]); function bar() { trueconsole.log(Object.prototype.toString.call(this)); } bar.call(7); * Notes: * call(this,arg[0],arg[1],...);我们用这个函数去调用没法直接调用的方法 */
|
bind方法与this
作用同call/apply,更简单高效ES5支持
function f(){ truereturn this.a; } var g = f.bind({a : "test"}); console.log(g()); var o = {a : 37, f : f, g : g}; console.log(o.f(), o.g());
|
参数属性与arguments
function foo(x,y) { trueconsole.log(x,y,this); } foo.call(100,1,2); foo.apply(true,[3,4]); foo.apply(null); foo.apply(undefined);
|
apply/call 方法(浏览器)
function foo(x,y){ 'use sttic'; console.log(x,y,this); } foo.apply(null); foo.apply(undefined);
|
bind方法
this.x=9; var module={ truex:81, truegetX: function(){ truetruereturn this.x; true} }; module.getX(); var getX = module.getX; getX(); var boundGetX=getX.bind(module); boundGetX();
|
bing与currying
function add(a,b,c){ return a+b+c; } var func=add.bind(undefined,100); func(3); var func2=func.bind(undefined,200); func2(10);
|
function getConfig(colors,size,otherOptions){ trueconsole.log(colors,size,otherOptions); } var defaultConfig=getConfig.bind(null,"#CC0000","1024*768"); defaultConfig("123"); degaultConfig("456");
|
bind 与 new
function foo(){ this.b=100; return this.a; } var func = foo.bind({a:1}); func(); new func();
|
闭包
!function(){ truevar localData="localData here"; truedocument.addEventListener('click', truefunction(){ truetrueconsole.log(localData); true}); }(); !function(){ truevar localData="localData here"; truevar url="http://www.wanglinzhizhi.me/"; true$.ajax({ truetrueurl:url, truetruesucess:function(){ truetruetrue truetruetrueconsole.log(localData); truetrue} true}); }();
|
闭包常见错误之循环闭包
document.body.innerHTML="<div id=div1>aa</div>"+"<div id=div2>bbb</div><div id=div3>ccc</div>"; for(var i=0;i<4;i++){ document.getElementById('div'+i).addEventListener('click',function(){ alert(i); true}); }
|
改正如下:
document.body.innerHTML="<div id=div1>aa</div>" +"<div id=div2>bbb</div><div id=div3>ccc</div>"; for(var i=1;i<4;i++){ !function(i){ document.getElementById('div'+i).addEventListener('click',function(){ alert(i); }); }(i); };
|
闭包-封装
!function(){ var _userId=2345; var _typeId='item'; var export={}; function converter(userId){ return +userId; } export.getUserId=function(){ return converter(_userId); } export.getTypeId=function(){ return _typeId; } window.export=export; }()); export.getUserId(); export.getTypeId(); export._userId; export._typeId; export.converter;
|
闭包的概念
在计算机科学中,闭包(也称词法闭包或函数闭包)是指一个函数或函数的引用,与一个引用环境绑定在一起。这 个引用环境是一个存储该函数每个非局部变量(也叫自由变量)的表。
闭包,不同于一般的函数,它允许一个函数在立即词法作用域外调用时,仍可访问非本地变量。
from 维基百科
闭包-小结
优点
缺点
作用域
作用域(全局、函数、eval)
var a = 10; (function() { truevar b = 20; })(); console.log(a); console.log(b); for (var item in {a : 1, b : 2}) { trueconsole.log(item); } console.log(item);
|
作用域链
function outer2(){ truevar local2=1; truefunction outer1(){ truetruevar local1=1; truetrue truetrueconsole.log(local1, local2, global3); true} trueouter1(); } var global3=1; outer2(); function outer(){ truevar i=1; truevar func=new Function("console.log(typeof i);"); truefunc(); } outer();
|
利用函数作用域封装
(function(){ var a,b; })(); !function(){ var a,b; }();
|
个人心得:
以前在学C++,Java的时候没觉得面向对象怎么怎么样,觉得继承也好,重载也好,就应该是那样的,没什么了不起的.现在学Javascript感慨JavaScript是彻头彻尾的面向对象啊(嗯?哦,我知道它是函数式啦),各种设计模式满天飞啊~~
ES6/7 Balel太提高生产力了